#include "TableWidgetPageShell.h"
#include "../../Utility/XXlogger.h"

TableWidgetPageShell::TableWidgetPageShell(QObject *parent):QObject (parent){
    connect(&_tableShell,&TableWidgetShell::sigDataChanged,this,&TableWidgetPageShell::tableShell_onDataChanged);
    connect(&_tableShell,&TableWidgetShell::sigEvent,this,&TableWidgetPageShell::sigEvent);
    connect(&_pageShell,&PageSelectionShell::sigEvent,this,&TableWidgetPageShell::pageShell_onEvent);
    _indexKey = "";
    _rowRtCal = nullptr;
}

// shell
void TableWidgetPageShell::shellTable(QTableWidget *tableWidget){
    _tableShell.shell(tableWidget);
}
void TableWidgetPageShell::shellPage(QAbstractButton *first, QAbstractButton *previous, QLabel *page, QAbstractButton *next, QAbstractButton *last, QLineEdit *pageSwitch, QComboBox *availableCountPerPage, QLabel *total){
    _pageShell.shell(first,previous,page,next,last,pageSwitch,availableCountPerPage,total);
}

// config
void TableWidgetPageShell::configColumn(const QStringList titles, const QStringList &keys, const QList<QMetaObject> &cls){
    _tableShell.configColumn(titles,keys,cls);
}
//void TableWidgetPageShell::configColumnRtCal(const QString &key, std::function<QString(QVariantMap)> rtCal){
//    _keyToRtCal[key] = rtCal;
//}
void TableWidgetPageShell::configColumnIndex(const QString &key){
    _indexKey = key;
}
void TableWidgetPageShell::configRowRtCal(std::function<void(QVariantMap &rowData, bool &rowSelected)> rtCal){
    _rowRtCal = rtCal;
}
void TableWidgetPageShell::configCountPerPage(int count, QList<int> available){
    _pageShell.consetCountPerPage(count,available);
}

// action
void TableWidgetPageShell::appendData(const QVariantMap &data){
    _data.append(data);
    _pageShell.appendItem();
}
void TableWidgetPageShell::insertDataAtRow(int row, const QVariantMap &data){
    int index = _pageShell.getIndexFromRowInPage(row);
    insertDataAtIndex(index,data);
}
void TableWidgetPageShell::insertDataAtIndex(int index, const QVariantMap &data){
    _data.insert(index,data);
    _pageShell.insertItem(index);

    QStringList names;
    QStringList caseIDs;
    for(int index=0; index<_data.count(); index++){
        auto map = _data[index].toMap();
        names << map["caseName"].toString();
        caseIDs << map["caseID"].toString();
    }
    //xxLogStr(names.join("."));
    //xxLogStr(caseIDs.join("."));
}
void TableWidgetPageShell::removeDataAtRow(int row){
    int index = _pageShell.getIndexFromRowInPage(row);
    removeDataAtIndex(index);
}
void TableWidgetPageShell::removeDataAtIndex(int index){
    _data.removeAt(index);
    _pageShell.removeItemAtIndex(index);
}

QVariantList TableWidgetPageShell::getDataAll(){
    return _data;
}
QVariantList TableWidgetPageShell::getData(){
    return _tableShell.getData();
}
QVariantMap TableWidgetPageShell::getDataAtRow(int row){
    int index = _pageShell.getIndexFromRowInPage(row);
    return getDataAtIndex(index);
}
QVariantMap TableWidgetPageShell::getDataAtIndex(int index){
    QStringList names;
    QStringList caseIDs;
    for(int index=0; index<_data.count(); index++){
        auto map = _data[index].toMap();
        names << map["caseName"].toString();
        caseIDs << map["caseID"].toString();
    }
    xxLog("index:%d",index);
    xxLogStr(names.join("."));
    xxLogStr(caseIDs.join("."));

    return _data.value(index).toMap();
}
QVariantMap TableWidgetPageShell::takeDataAtRow(int row){
    int index = _pageShell.getIndexFromRowInPage(row);
    QVariantMap data = _data.takeAt(index).toMap();
    _pageShell.removeItemAtIndex(index);
    return data;
}

void TableWidgetPageShell::setDataAll(const QVariantList &datas){
    _data = datas;
    _pageShell.blockSignals(true);
    _pageShell.reset(_data.count());
    _pageShell.blockSignals(false);
    updateTable();
}
void TableWidgetPageShell::setDataAtRow(int row, const QVariantMap &data){
    int index = _pageShell.getIndexFromRowInPage(row);
    _data.replace(index,data);
    _tableShell.setData(row,data);
}
void TableWidgetPageShell::setDataAtIndex(int index, const QVariantMap &data){
    int row = _pageShell.getRowFromIndex(index);
    _data.replace(index,data);
    _tableShell.setData(row,data);
}
void TableWidgetPageShell::updateDataAtRow(int row, const QVariantMap &data){
    int index = _pageShell.getIndexFromRowInPage(row);
    _tableShell.updateData(row,data);
    _data.replace(index,_tableShell.getData(row));
}
void TableWidgetPageShell::updateDataAtIndex(int index, const QVariantMap &data){
    QStringList names;
    QStringList caseIDs;
    for(int index=0; index<_data.count(); index++){
        auto map = _data[index].toMap();
        names << map["caseName"].toString();
        caseIDs << map["caseID"].toString();
    }
    xxLog("index:%d",index);
    xxLogStr(names.join("."));
    xxLogStr(caseIDs.join("."));

    int row = _pageShell.getRowFromIndex(index);
    _tableShell.updateData(row,data);
    auto map = _tableShell.getData(row);
    _data.replace(index,_tableShell.getData(row));

    names.clear();
    caseIDs.clear();
    for(int index=0; index<_data.count(); index++){
        auto map = _data[index].toMap();
        names << map["caseName"].toString();
        caseIDs << map["caseID"].toString();
    }
    xxLog("index:%d",index);
    xxLogStr(names.join("."));
    xxLogStr(caseIDs.join("."));
}
void TableWidgetPageShell::updateDataEqualTo(const QVariantMap equalTo, const QVariantMap &data){
    int index = findIndexEqualTo(equalTo);
    if(index<0){
        xxErrStrF(("could not find target. \n"
                   "equalTo:%1").arg(XXqtDefine::variantToJsonString(equalTo,true)));
        return;
    }
    xxLogStrF(("\nindex:%1"
               "\nequalTo:%2").arg(index).arg(XXqtDefine::variantToJsonString(equalTo,true)));
    if(_pageShell.isIndexAtCurrentPage(index)){
        updateDataAtIndex(index,data);
    }
    else{
        xxLogStrF(("\nindex:%1"
                   "\nequalTo:%2").arg(index).arg(XXqtDefine::variantToJsonString(_data[index].toMap(),true)));
        auto source = _data[index].toMap();
        for (auto iter=data.begin(); iter!=data.end(); iter++) {
            source[iter.key()] = iter.value();
        }
        _data[index] = source;
        xxLogStrF(("\nindex:%1"
                   "\nequalTo:%2").arg(index).arg(XXqtDefine::variantToJsonString(_data[index].toMap(),true)));
    }
}

int TableWidgetPageShell::findIndexEqualTo(const QVariantMap &data){
    for (int row=0; row<_data.count(); row++) {
        QVariantMap map = _data[row].toMap();
        bool matching = true;
        for (auto iter=data.begin(); iter!=data.end(); iter++) {
            if(!map.contains(iter.key()) || map.value(iter.key()) != iter.value()){
                matching = false;
                break;
            }
        }
        if(matching){
           return row;
        }
    }
    return -1;
}
void TableWidgetPageShell::selectAtRow(int row){
    _tableShell.select(row);
}
void TableWidgetPageShell::selectAtIndex(int index){
    if(!_pageShell.isCurrentPage(index)){
        return;
    }
    int row = _pageShell.getRowFromIndex(index);
    _tableShell.select(row);
}

void TableWidgetPageShell::updateTable(){
    int selectRow = -1;
    int startIndex = _pageShell.getBeginIndexInPage();
    int count = _pageShell.getCountInPage();

    auto pageData = _data.mid(startIndex,count);
    for (int row=0; row<count; row++) {
        QVariantMap map = pageData[row].toMap();
        if(!_indexKey.isEmpty()){
            map[_indexKey] = QString::number(row+1);
        }
        if(_rowRtCal){
            bool rowSelected = false;
            _rowRtCal(map,rowSelected);
            if(rowSelected){
                selectRow = row;
            }
        }
        pageData[row] = map;
    }
    _tableShell.setData(pageData);
    _tableShell.select(selectRow);
}

void TableWidgetPageShell::tableShell_onEvent(int row, QString name, QVariant info){
    emit sigEvent(row,name,info);
}
void TableWidgetPageShell::tableShell_onDataChanged(int row){
    int index = _pageShell.getIndexFromRowInPage(row);
    _data.replace(index,_tableShell.getData(row));
    xxLog("data changed. row:%d index:%d",row,index);
}
void TableWidgetPageShell::pageShell_onEvent(QString name, QVariant info){
    Q_UNUSED(info);
    if(name == PageSelectionShell::kSigNeedUpdate){
        updateTable();
    }
}
